package cn.jaychang.demo.resource.config;

import lombok.AllArgsConstructor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.token.DefaultTokenServices;
import org.springframework.security.oauth2.provider.token.ResourceServerTokenServices;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;

/**
 * `@EnableResourceServer` 标记这是一个资源服务
 * `@EnableGlobalMethodSecurity` 该注解开启注解校验权限
 *
 * @author jaychang
 * @since 2024/5/21
 **/
@Configuration
@EnableResourceServer
@EnableGlobalMethodSecurity(prePostEnabled = true,jsr250Enabled = true,securedEnabled = true)
@AllArgsConstructor
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {

    private final TokenStore tokenStore;

    private final JwtAccessTokenConverter jwtAccessTokenConverter;

    /**
     * 配置令牌校验服务，客户端携带令牌访问资源，作为资源端必须校验令牌的真伪
     * [ 注意：远程校验令牌存在性能问题，但是后续使用JWT令牌则本地即可进行校验，不必远程校验了。  ]
     *
     * @return
     */
    @Bean
    public ResourceServerTokenServices tokenServices() {
        // 远程调用授权服务的check_token进行令牌的校验
        DefaultTokenServices tokenServices = new DefaultTokenServices();
        tokenServices.setTokenStore(tokenStore);
        // 令牌的增强JwtAccessTokenConverter
        tokenServices.setTokenEnhancer(jwtAccessTokenConverter);
        return tokenServices;
    }

    /**
     * 配置资源ID和令牌校验服务
     *
     * @param resources
     * @throws Exception
     */
    @Override
    public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
        resources.resourceId("res01")
                .tokenServices(tokenServices());
    }

    /**
     * 配置security安全机制
     * @param http
     * @throws Exception
     */
    @Override
    public void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers("/**").access("#oauth2.hasAnyScope('all')")
                .anyRequest().authenticated();
    }
}
